#pragma once

#include <core/noncopyable.h>
#include <core/smart_ptr.h>

#include "vector2.h"
#include "vector3.h"

#include "Zone.h"




namespace math
{
   template
   <
      typename float_t
   >
   class ParticleEmitter : public core::noncopyable
   {
   public:

      typedef float_t            float_t;
      typedef vector2<float_t>   vector2_t;
      typedef vector3<float_t>   vector3_t;

   private:

      /// Current number of particles in the tank
      int         m_tank;

      /// The particle spawn rate (#nbr of particles that are generated per second)
      /// A value of -1 means that all particles are spawned instantly
      float_t     m_rate;

      /// Minimum and maximum velocity that is applied to a spawning particle
      vector2_t   m_velocity;

      /// The zone this emitter spawns its particles in
      ZonePtr     m_zone;

   public:

      ParticleEmitter(int tank, float_t rate, const vector2_t& velocity, const ZonePtr& zone)
         : m_tank(tank)
         , m_rate(rate)
         , m_velocity(velocity)
         , m_zone(zone)
      {}

      virtual ~ParticleEmitter() {}



      /**
       * Get the number of particles in the emitter's tank.
       * A return value of -1 means the tank has an infinite amount of particles.
       */
      int tank() const
      {
         return m_tank;
      }

      /**
       * Set the number of particles in the emitter's tank.
       * A value of -1 means the tank has an infinite amount of particles.
       */
      virtual void setTank(int tank)
      {
         m_tank = tank;
      }



      /**
       * Get the rate at which the particles are generated.
       */
      float_t rate() const
      {
         return m_rate;
      }

      /**
       * Set the rate at which the particles are generated.
       */
      virtual void setRate(float_t rate)
      {
         m_rate = rate;
      }



      /**
       * Get the minimum and maximum velocity that is applied to a particle.
       */
      vector2_t velocity() const
      {
         return m_velocity;
      }

      /**
       * Set the minimum and maximum velocity that is applied to a particle.
       */
      virtual void setVelocity(const vector2_t& velocity)
      {
         m_velocity = velocity;
      }



      /**
       * Get the Zone of the ParticleEmitter.
       */
      void ZonePtr zone() const
      {
         return m_zone;
      }



      /**
       * Generate a velocity for a new particle.
       */
      virtual vector3_t generateVelocity() const = 0;

      /**
       * Generate a position for a new particle.
       */
      virtual vector3_t generatePosition() const = 0;
   };
   ///////////////////////////////////////////////////////////////////////////////////////////////




   typedef core::smart_ptr<ParticleEmitter> ParticleEmitterPtr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
